{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from neighbours.knn import KNeighborsClassifier\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "from sklearn.preprocessing import StandardScaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_data(path):\n",
    "        f = open(path)\n",
    "        label = []\n",
    "        data = []\n",
    "        for line in f.readlines():\n",
    "            line = line.strip().split('\\t')\n",
    "            label.append(int(line[-1])-1)\n",
    "            data.append(list(map(float, line[:-1])))\n",
    "        f.close()\n",
    "        return np.array(data), np.array(label)\n",
    "\n",
    "\n",
    "def split_data(data, label):\n",
    "    train_size = int(data.shape[0] * 0.7)\n",
    "    \n",
    "    train_data = data[: train_size]\n",
    "    train_label = label[: train_size]\n",
    "    norm = StandardScaler()\n",
    "    norm.fit(train_data)\n",
    "    train_data = norm.transform(train_data)\n",
    "\n",
    "    test_data = data[train_size:]\n",
    "    test_label = label[train_size:]\n",
    "    test_data = norm.transform(test_data)\n",
    "    \n",
    "    return train_data, train_label, test_data, test_label"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test knn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "best Ks are [ 1 25]\n"
     ]
    }
   ],
   "source": [
    "data, label = load_data('./data/knn/datingTestSet2.txt')\n",
    "train_data, train_label, test_data, test_label = split_data(data, label)\n",
    "acc_list = []\n",
    "for k in range(1, 31):\n",
    "    knn = KNeighborsClassifier(n_neighbors=k)\n",
    "    knn.fit(train_data, train_label)\n",
    "    y_pred = knn.predict(test_data)\n",
    "    acc = (y_pred == test_label).sum() / test_label.shape[0]\n",
    "    acc_list.append(acc)\n",
    "plt.plot(list(range(1,31)), acc_list)\n",
    "plt.show()\n",
    "best = np.max(acc_list)\n",
    "best = np.where(acc_list == best)[0] + 1\n",
    "print(f'best Ks are {best}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Compare the compute cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.018002748489379883\n",
      "0.9533333333333334\n",
      "0.017011165618896484\n",
      "0.9533333333333334\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "knn = KNeighborsClassifier(algorithm='kd_tree')\n",
    "knn.fit(train_data, train_label)\n",
    "time_now = time.time()\n",
    "results = knn.predict(test_data)\n",
    "cost_kd = time.time() - time_now\n",
    "print(cost_kd)\n",
    "acc = (results == test_label).sum() / test_label.shape[0]\n",
    "print(acc)\n",
    "\n",
    "\n",
    "knn = KNeighborsClassifier(n_neighbors=5)\n",
    "knn.fit(train_data, train_label)\n",
    "time_now = time.time()\n",
    "results = knn.predict(test_data)\n",
    "cost_naive = time.time() - time_now\n",
    "print(cost_naive)\n",
    "acc = (results == test_label).sum() / test_label.shape[0]\n",
    "print(acc)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.7 ('torch10')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "8f5c1b24a4ab56abd916d54534896e4f6d0a89a0daba3b8db7ea16393a780e2e"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
